package com.k.kc.util.date;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.k.kc.util.DateUtils;
import com.k.kc.util.date.model.MonthVO;
import com.k.kc.util.date.model.RiLiNode;
import com.k.kc.util.date.model.WeekVO;
import com.k.kc.util.date.model.YearVO;
import com.k.kc.util.json.jackson.JacksonUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * @author k
 */
public class RiLi {
    static final String[] WEEKS = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

    private static String getFirstWeekOfTheMonth(int year, int month) {
        Calendar calender = Calendar.getInstance();
        calender.set(year, month, 1);
        return WEEKS[calender.get(Calendar.DAY_OF_WEEK) - 1];
    }

    /**
     * @param count [0,1,2...]
     * @param std   标准日历
     * @return [1, 2, 3, 4, 5, 6, 7]
     */
    private static int formatWeek(int count, boolean std) {
        int i = count % 7;
        return std ? (i == 0 ? 7 : i) : i + 1;
    }

    /**
     * @param year       year
     * @param month      1 -12
     * @param std        true:周日至周六  false:周一至周日
     * @param dynamicRow true:dynamic  false:6 row
     */
    public static List<RiLiNode> printRiLi(int year, int month, boolean std, boolean dynamicRow) {
        List<RiLiNode> list = new ArrayList<>();
        String title = std ? "日\t一\t二\t三\t四\t五\t六" : "一\t二\t三\t四\t五\t六\t日";
        int monthTotalDays = DateUtils.getDaysOfMonth(year, month);
        int count = 0;
        System.out.print("\r\n" + year + "年" + month + "月的日历表" + "\r\n");
        System.out.println(title);
        {
            // 上个月数据,补齐第一周
            int preNodeLength = getPreNodeLength(year, month, std);
            // 跨年问题
            int myMonth = month == 1 ? 12 : month - 1;
            int myYear = month == 1 ? year - 1 : year;
            int preMonthDays = DateUtils.getDaysOfMonth(myYear, myMonth);
            // 补上月节点, 需要从上个月最后一天递减补齐
            for (int i = preNodeLength; i > 0; i--) {
                int preNode = preMonthDays - i + 1;
                System.out.print(/*"前"*/preNode + "\t");
                RiLiNode node = RiLiNode.newBuilder().setYear(myYear).setMonth(myMonth).setDay(preNode).setWeek(formatWeek(count, std)).build();
                list.add(node);
                count += 1;
            }
        }

        // 本月数据
        for (int i = 1; i <= monthTotalDays; i++) {
            System.out.print(i + "\t");
            RiLiNode node = RiLiNode.newBuilder().setYear(year).setMonth(month).setDay(i).setWeek(formatWeek(count, std)).build();
            list.add(node);
            count += 1;
            if (count % 7 == 0) {
                System.out.println();
            }
        }

        {
            // 下个月数据,补齐最后一周
            // 42-count 补够6行 or 7-(count%7) 补够最后一行
            int myCount = dynamicRow ? 7 - (count % 7) : 42 - count;
            // 跨年问题
            int myMonth = month == 12 ? 1 : month + 1;
            int myYear = month == 12 ? year + 1 : year;
            // 补齐下个月节点,直接从1递增补齐
            for (int i = 1; i <= myCount; i++) {
                System.out.print(/*"后"*/i + "\t");
                RiLiNode node = RiLiNode.newBuilder().setYear(myYear).setMonth(myMonth).setDay(i).setWeek(formatWeek(count, std)).build();
                list.add(node);
                count += 1;
                if (count % 7 == 0) {
                    System.out.println();
                }
            }
        }
        return list;
    }

    private static int getPreNodeLength(int year, int monthChina, boolean std) {
        String week = getFirstWeekOfTheMonth(year, monthChina - 1);
        int preNodeLength = 0;
        if (std) {
            // 日 一 二 三 四 五 六
            for (int j = 0; j < WEEKS.length; j++) {
                if (WEEKS[j].equals(week)) {
                    preNodeLength = j;
                }
            }
        } else {
            // 一 二 三 四 五 六 日
            for (int i = 0; i < WEEKS.length; i++) {
                if (WEEKS[i].equals(week)) {
                    if (i == 0) {
                        preNodeLength = 6;
                    } else {
                        preNodeLength = i - 1;
                    }
                }
            }
        }
        System.out.println("year:"+year+" monthChina:"+monthChina+" week:"+week+"  preNodeLength:"+preNodeLength);
        return preNodeLength;
    }

    public static void  printRiLi(int year, int startMonth, int endMonth, boolean weekStd, boolean dynamicRow){
        YearVO yearVO = new YearVO();
        yearVO.setYear(year+"");
        List<MonthVO> months = new ArrayList<>();
        for (int i = startMonth; i <= endMonth; i++) {
            Integer month = i;
            List<RiLiNode> list = printRiLi(year, i, weekStd, dynamicRow);
            MonthVO monthVO = new MonthVO();
            List<WeekVO> weekList =new ArrayList<>();
            List<RiLiNode> nodeList = new ArrayList<>();
            int weekOfMonth = 1;
            for (int j = 0; j < list.size(); j++) {
                RiLiNode node = list.get(j);
                String monthNode = node.getMonth() < 10 ? "0" + node.getMonth() : "" + node.getMonth();
                String day = node.getDay() < 10 ? "0" + node.getDay() : "" + node.getDay();
                String week = "" + node.getWeek();
                String itm = String.format("%s-%s-%s-%s\t", node.getYear(), monthNode, day, week);
                System.out.print(itm);
                nodeList.add(node);
                if ((j + 1) % 7 == 0) {
                    System.out.println();
                    WeekVO weekVO = new WeekVO();
                    weekVO.setWeekOfMonth(weekOfMonth+"");
                    weekVO.setWeekStd(weekStd);
                    weekVO.setDays(nodeList);
                    weekList.add(weekVO);
                    nodeList = new ArrayList<>();
                    weekOfMonth ++ ;
                }
                monthVO.setMonth(month+"");
                monthVO.setWeeks(weekList);
            }
            months.add(monthVO);
        }
        yearVO.setMonths(months);
        try {
            String json = JacksonUtils.getMapper().writeValueAsString(yearVO);
            System.out.println(json);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
//        long start = System.currentTimeMillis();
//        int year = 2024;
//        int monthOfYear = 2;
//        for (int i = 1; i <= monthOfYear; i++) {
//            List<RiLiNode> list = printRiLi(year, i, false, true);
//            for (int j = 0; j < list.size(); j++) {
//                RiLiNode node = list.get(j);
//                String month = node.getMonth() < 10 ? "0" + node.getMonth() : "" + node.getMonth();
//                String day = node.getDay() < 10 ? "0" + node.getDay() : "" + node.getDay();
//                String week = "" + node.getWeek();
//                String itm = String.format("%s-%s-%s-%s\t", node.getYear(), month, day, week);
//                System.out.print(itm);
//                if ((j + 1) % 7 == 0) {
//                    System.out.println();
//                }
//            }
//        }
//        long end = System.currentTimeMillis();
//        System.out.println(end - start);
        printRiLi(2024,1,1,false,false);
    }
}
